﻿using DevExpress.XtraBars.Docking2010.Views;
using DevExpress.XtraBars.Docking2010.Views.Widget;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using XCI.Core;
using XCI.Extensions;
using XCI.Helper;

namespace XCI.Windows
{
    /// <summary>
    /// 部件对象
    /// </summary>
    public class WidgetObject
    {
        private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
        private readonly LoadingMask loadingPanel;
        private ServerFile dataFile;
        private ServerFile settingFile;
        private readonly Random random = new Random();
        private JsonFile<List<string>> list;

        public string Code { get; }
        public WidgetView WidgetView { get; }
        public List<string> WidgetData => list.Data;
        public Dictionary<string, IWidget> WidgetControls { get; private set; }
        public bool HasItem => list.Data.Count > 0;

        public WidgetObject(WidgetView widgetView, string code)
        {
            if (string.IsNullOrEmpty(code)) throw new ArgumentNullException(nameof(code), "请指定部件编码");

            this.Code = code;
            this.WidgetView = widgetView;
            this.loadingPanel = new LoadingMask(widgetView.Manager.ContainerControl);
        }

        public async Task LoadAsync()
        {
            await loadingPanel.ShowAsync(async () =>
            {
                dataFile = CrreateServerFile($"{Code}.json");
                settingFile = CrreateServerFile($"{Code}.xml");

                var dataTask = dataFile.DownloadAsync();
                var settingTak = settingFile.DownloadAsync();
                await Task.WhenAll(dataTask, settingTak);

                list = new JsonFile<List<string>>(dataFile.LocalFilePath);
                InitWidgetSetting();
            });
        }

        public async Task ResetAsync()
        {
            await loadingPanel.ShowAsync(async () =>
            {
                IOHelper.DeleteFile(dataFile.LocalFilePath);
                IOHelper.DeleteFile(settingFile.LocalFilePath);
                var dataTask = dataFile.DeleteAsync();
                var settingTask = settingFile.DeleteAsync();
                await Task.WhenAll(dataTask, settingTask);
                InitWidgetSetting();
            });
        }

        /// <summary>
        /// 创建服务器数据文件
        /// </summary>
        /// <param name="name">文件名称</param>
        public ServerFile CrreateServerFile(string name)
        {
            string localCatalog = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDefaultSettings.WidgetStoreLocalRootCatalog);
            string serverCatalog = $"/{AppDefaultSettings.WidgetStoreServerRootCatalog}";
            return new ServerFile(localCatalog, serverCatalog, $"{name}");
        }

        private void InitWidgetSetting()
        {
            try
            {
                WidgetView.QueryControl += widgetView_QueryControl;
                WidgetView.DocumentClosed += widgetView_DocumentClosed;
                WidgetView.PopupMenuShowing += widgetView_PopupMenuShowing;
                WidgetView.BeginUpdateAnimation();
                WidgetView.FlowLayoutProperties.FlowLayoutItems.Clear();
                WidgetView.FreeLayoutProperties.FreeLayoutItems.Clear();
                foreach (var t in WidgetView.StackGroups)
                {
                    t.Items.Clear();
                }
                WidgetView.Documents.Clear();
                WidgetControls = new Dictionary<string, IWidget>();
                foreach (var item in list.Data)
                {
                    try
                    {
                        var widgetInstance = ObjectHelper.CreateInstance<IWidget>(item);
                        if (widgetInstance == null) continue;
                        WidgetControls.Add(item, widgetInstance);
                        var documentInstance = widgetInstance.CreateDocument();
                        documentInstance.ControlName = item;
                        WidgetCaptionAttribute attr = ObjectHelper.GetAttribute<WidgetCaptionAttribute>(widgetInstance.GetType());
                        if (attr != null)
                        {
                            var caption = attr.Caption;
                            if (string.IsNullOrEmpty(caption))
                            {
                                caption = attr.Name;
                            }
                            documentInstance.Caption = caption;
                        }
                        //documentInstance.ControlTypeName = item;
                        widgetInstance.Init(documentInstance);
                        WidgetView.Documents.Add(documentInstance);
                    }
                    catch (System.Exception e)
                    {
                        Logger.Error(e, "加载部件出错,部件实现类:"+ item);
                    }
                }
                if (File.Exists(settingFile.LocalFilePath))
                {
                    WidgetView.RestoreLayoutFromXml(settingFile.LocalFilePath);
                }
                else
                {
                    WidgetView.ResetDocumentAnimationProperties();
                    WidgetView.ResetFlowLayoutProperties();
                    WidgetView.ResetFreeLayoutProperties();

                    if (WidgetView.StackGroups.Count == 0)
                    {
                        StackGroup stackGroup1 = new StackGroup();
                        StackGroup stackGroup2 = new StackGroup();
                        StackGroup stackGroup3 = new StackGroup();
                        WidgetView.StackGroups.AddRange(new[] { stackGroup1, stackGroup2, stackGroup3 });
                    }
                    if (WidgetView.Rows.Count == 0 && WidgetView.Columns.Count == 0)
                    {
                        ColumnDefinition columnDefinition1 = new ColumnDefinition();
                        ColumnDefinition columnDefinition2 = new ColumnDefinition();
                        ColumnDefinition columnDefinition3 = new ColumnDefinition();
                        RowDefinition rowDefinition1 = new RowDefinition();
                        RowDefinition rowDefinition2 = new RowDefinition();
                        RowDefinition rowDefinition3 = new RowDefinition();
                        WidgetView.Columns.AddRange(new[] { columnDefinition1, columnDefinition2, columnDefinition3 });
                        WidgetView.Rows.AddRange(new[] { rowDefinition1, rowDefinition2, rowDefinition3 });
                    }
                }
            }
            finally
            {
                WidgetView.EndUpdateAnimation();
            }
        }

        /// <summary>
        /// 设置数据项
        /// </summary>
        public void SetItems(List<string> items)
        {
            list.SetData(items);
        }

        /// <summary>
        /// 保存数据项
        /// </summary>
        public async Task SaveItemsAsync()
        {
            list.Save();
            await dataFile.UploadAsync();
        }

        /// <summary>
        /// 保存View布局
        /// </summary>
        public async Task SaveLayoutAsync()
        {
            IOHelper.CreateDirectoryByPath(settingFile.LocalFilePath);
            WidgetView.SaveLayoutToXml(settingFile.LocalFilePath);
            await settingFile.UploadAsync();
        }

        /// <summary>
        /// 设计
        /// </summary>
        public void Design()
        {
            var designFrom = new FrmWidgetDesign(Code);
            designFrom.ShowDialog();
            designFrom.Dispose();
        }

        /// <summary>
        /// 表格布局混合
        /// </summary>
        public void TableLayoutMix()
        {
            try
            {
                WidgetView.BeginUpdateAnimation();
                var points = new List<Point>();
                for (int i = 0; i < WidgetView.Rows.Count; i++)
                {
                    for (int j = 0; j < WidgetView.Columns.Count; j++)
                    {
                        points.Add(new Point(i, j));
                    }
                }
                foreach (var doc in WidgetView.Documents)
                {
                    var newLocation = points[random.Next(points.Count)];
                    if (doc is Document document)
                    {
                        document.RowIndex = newLocation.Y;
                        document.ColumnIndex = newLocation.X;
                    }
                    points.Remove(newLocation);
                }
            }
            finally
            {
                WidgetView.EndUpdateAnimation();
            }
        }

        /// <summary>
        /// 流式布局混合
        /// </summary>
        public void FlowLayoutMix()
        {
            try
            {
                WidgetView.BeginUpdateAnimation();
                for (int i = 0; i < WidgetView.FlowLayoutProperties.FlowLayoutItems.Count; i++)
                {
                    var index = random.Next(WidgetView.Documents.Count);
                    if (i == index) continue;
                    var document = WidgetView.FlowLayoutProperties.FlowLayoutItems[i];
                    WidgetView.FlowLayoutProperties.FlowLayoutItems.Remove(document);
                    WidgetView.FlowLayoutProperties.FlowLayoutItems.Insert(index, document);
                }
            }
            finally
            {
                WidgetView.EndUpdateAnimation();
            }
        }

        /// <summary>
        /// 堆栈布局混合
        /// </summary>
        public void StackLayoutMix()
        {
            try
            {
                WidgetView.BeginUpdateAnimation();
                foreach (var doc in WidgetView.Documents)
                {
                    if (!(doc is Document document)) continue;
                    var oldGroup = document.Parent;
                    oldGroup?.Items.Remove(document);
                    var randomIndex = random.Next(WidgetView.StackGroups.Count);
                    WidgetView.StackGroups[randomIndex].Items.Add(document);
                }
            }
            finally
            {
                WidgetView.EndUpdateAnimation();
            }
        }

        private void widgetView_QueryControl(object sender, QueryControlEventArgs e)
        {
            if (string.IsNullOrEmpty(e.Document.ControlName))
            {
                e.Control = new Control();
                return;
            }

            if (WidgetControls.TryGetValue(e.Document.ControlName, out IWidget widget) && widget != null)
            {
                e.Control = widget as Control;
            }
        }

        private void widgetView_DocumentClosed(object sender, DocumentEventArgs e)
        {
            list.Data.RemoveIf(p => p.Equals(e.Document.ControlName));
            WidgetControls.Remove(e.Document.ControlName);
        }

        private void widgetView_PopupMenuShowing(object sender, DevExpress.XtraBars.Docking2010.Views.PopupMenuShowingEventArgs e)
        {
            if (!e.HitInfo.IsEmpty)
            {
                e.Cancel = true;
            }
        }
    }

    /// <summary>
    /// 部件组件对象信息
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class WidgetCaptionAttribute : ComponentCaptionAttribute
    {
        /// <summary>
        /// 初始化 WidgetCaptionAttribute 类的新实例。
        /// </summary>
        public WidgetCaptionAttribute()
        {
        }

        /// <summary>
        /// 初始化 WidgetCaptionAttribute 类的新实例。
        /// </summary>
        public WidgetCaptionAttribute(bool visible) : base(visible)
        {
        }

        /// <summary>
        /// 初始化 WidgetCaptionAttribute 类的新实例。
        /// </summary>
        /// <param name="name">名称</param>
        public WidgetCaptionAttribute(string name) : base(name)
        {
        }
    }
}